package jmine.tec.environment.db.server;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.dbcp.BasicDataSource;

/**
 * @author Rafael Volpato
 * @author Gustavo Almeida
 */
public abstract class AbstractTestDBServer implements TestDBServer {

    protected BasicDataSource dataSource;

    private String defaultSchema;

    /**
     * Devolve os nomes das tabelas presentes no banco.
     * 
     * @param connection conexão com o banco
     * @return lista com os nomes das tabelas.
     */
    protected List<String> getTableNames(Connection connection) {
        DatabaseMetaData metaData;
        try {
            metaData = connection.getMetaData();
        } catch (SQLException e) {
            throw new RuntimeException("Não foi possível obter metadados do banco", e);
        }

        ResultSet rs;
        try {
            String schema = "";
            String catalog = null;

            ResultSet rsSchemas = connection.getMetaData().getSchemas();
            while (rsSchemas.next()) {
                if (!rsSchemas.getString("TABLE_SCHEM").equalsIgnoreCase("INFORMATION_SCHEMA")) {
                    schema = rsSchemas.getString("TABLE_SCHEM");
                    try {
                        catalog = rsSchemas.getString("TABLE_CATALOG");
                    } catch (Exception e) {
                        // XXX pegar apenas a exception especifica
                    }
                }
            }
            rs = metaData.getTables(catalog, schema, "%", new String[]{ "TABLE" });
        } catch (SQLException e) {
            throw new RuntimeException("Não foi possível obter dados sobbre as tabelas", e);
        }

        List<String> tables = new LinkedList<String>();
        try {
            while (rs.next()) {
                tables.add(rs.getString("TABLE_NAME"));
            }
            rs.close();
        } catch (SQLException e) {
            throw new RuntimeException("Não foi possível obter nome das tabelas", e);
        }
        return tables;
    }

    /**
     * {@inheritDoc}
     */
    public void setDataSource(BasicDataSource dataSource) {
        this.dataSource = dataSource;

    }

    /**
     * {@inheritDoc}
     */
    public void setDefaultSchema(String defaultSchema) {
        this.defaultSchema = defaultSchema;
    }

    /**
     * {@inheritDoc}
     */
    public String getDefaultSchema() {
        return this.defaultSchema;
    }

    /**
     * {@inheritDoc}
     */
    public Connection getConnection() throws SQLException {
        return this.dataSource.getConnection();
    }

    /**
     * {@inheritDoc}
     */
    public String getDbName() {
        String url = this.dataSource.getUrl();

        String dbName = url.substring(url.lastIndexOf('/') + 1);
        if (dbName.indexOf('?') != -1) {
            dbName = dbName.substring(0, dbName.indexOf('?'));
        }

        return dbName;
    }
}
